import base64
import logging
import pickle

from django.conf import settings
from django_redis import get_redis_connection

logger = logging.getLogger("django")


def get_carts_from_cookies(request):
    """
    获取cookie购物车
    :param request: 请求对象
    :return: dict
    """
    carts_dict = {}
    carts_data = request.COOKIES.get(settings.COOKIE_CART)  # 从cookie获取用户购物车数据
    if carts_data:  # 判断cookie购物车数据是否为空
        carts_dict = pickle.loads(base64.b64decode(carts_data))  # 解码cookie购物车数据
    return carts_dict


def get_carts_cookie_data(carts):
    """
    获取用于cookie传输的购物车数据
    :param carts: 购物车数据
    :return: str
    """
    if carts:
        return base64.b64encode(pickle.dumps(carts)).decode()  # 编码cookie购物车数据
    return ""


def get_redis_carts(request):
    user_id = request.user.id
    redis_cart = None
    redis_selected = None

    conn = get_redis_connection('carts')
    # 读取购物车数据
    # redis_cart = {b"14": b"5"} 或者 返回None
    redis_cart = conn.hgetall('carts_%s'%user_id)
    # 读取选中信息
    # redis_selected={b"14"} 后者 返回None
    redis_selected = conn.smembers('selected_%s'%user_id)

    if not redis_cart:
        redis_cart = {} # 如果缓存不存在，则返回空字典
    if not redis_selected:
        redis_selected = set() # 如果缓存不存在则返回空集合

    return redis_cart, redis_selected

def merge_cart_cookie_to_redis(request, response):
    """
    用户登录后合并cookie购物车到用户购物车
    :param request: 请求对象
    :param response: 响应对象
    :return: 无cookie购物车的响应对象
    """
    '''获取cookie购物车数据'''
    carts_cookie = get_carts_from_cookies(request)  # 获取cookie购物车数据
    if not carts_cookie:  # 如果cookie中无购物车信息则不做合并
        return response

    '''合并用户购物车与cookie购物车'''
    user = request.user  # 获取用户对象
    redis_conn = get_redis_connection("carts")  # 获取redis数据库连接对象
    sku_id_list = carts_cookie.keys()  # 获取cookie购物车中的商品id
    try:
        for sku_id in sku_id_list:  # 遍历cookie购物车中的商品id
            # hash类型存储商品id到redis数据库(用户id和商品id覆盖更新，商品数量自动累加)
            redis_conn.hincrby(f"carts_{user.id}", sku_id, carts_cookie[sku_id]["count"])
            if carts_cookie[sku_id]["selected"]:  # 判断当前商品是否勾选
                redis_conn.sadd(f"selected_{user.id}", sku_id)  # set类型存储勾选商品id到redis数据库
    except Exception as e:
        logger.error(f"合并购物车时出错：{e}")
        return response

    '''删除响应体中cookie购物车信息'''
    response.delete_cookie(settings.COOKIE_CART)
    return response
